import { message } from "antd";
import type { Socket } from "socket.io-client";

interface UseSocketEventsProps {
  socket: Socket;
  peerConnections: Map<string, RTCPeerConnection>;
  initPeerConnection: (userId?: string) => RTCPeerConnection;
  setRemoteStreams: (streams: Map<string, MediaStream>) => void;
  remoteStreams: Map<string, MediaStream>;
  setPeerConnections: (pcs: Map<string, RTCPeerConnection>) => void;
  stream: MediaStream | null;
  roomId: string;
}

export const useSocketEvents = ({
  socket,
  peerConnections,
  initPeerConnection,
  setRemoteStreams,
  remoteStreams,
  setPeerConnections,
  stream,
  roomId,
}: UseSocketEventsProps) => {
  useEffect(() => {
    // 先清理之前的所有事件监听器
    const cleanupEvents = () => {
      socket.off("new-viewer");
      socket.off("viewer-joined");
      socket.off("offer");
      socket.off("answer");
      socket.off("ice-candidate");
      socket.off("user-left");
      socket.off("share-ended");
      socket.off("host-left");
      socket.off("viewer-left");
    };

    cleanupEvents(); // 先清理一次

    if (stream) {
      socket.on("new-viewer", async ({ userId, roomId, isNewJoin }) => {
        try {
          console.log(`新观众加入 ${userId}, isNewJoin: ${isNewJoin}`);
          message.info(`新观众加入 ${userId}`);

          // 检查是否已存在连接
          let pc = peerConnections.get(userId);
          if (pc) {
            // 如果连接已存在，先关闭旧连接
            pc.close();
          }

          pc = initPeerConnection(userId);

          // 添加本地媒体流
          stream.getTracks().forEach((track) => {
            pc.addTrack(track, stream);
          });

          // 创建并发送 offer
          const offer = await pc.createOffer();
          await pc.setLocalDescription(offer);

          peerConnections.set(userId, pc);
          setPeerConnections(new Map(peerConnections));

          socket.emit("offer", {
            offer,
            userId: socket.id,
            targetUserId: userId,
            roomId,
          });
        } catch (error) {
          console.error("为新观看者创建连接失败:", error);
          message.error("创建连接失败");
        }
      });

      socket.on("viewer-joined", async ({ userId, roomId }) => {
        console.log(`其他观众加入房间: ${userId}`);
        if (stream) {
          try {
            const pc = initPeerConnection(userId);

            stream.getTracks().forEach((track) => {
              pc.addTrack(track, stream);
            });

            const offer = await pc.createOffer();
            await pc.setLocalDescription(offer);

            peerConnections.set(userId, pc);
            setPeerConnections(new Map(peerConnections));

            socket.emit("offer", {
              offer,
              userId: socket.id,
              targetUserId: userId,
              roomId,
            });
          } catch (error) {
            console.error("为其他观众创建连接失败:", error);
          }
        }
      });
    }

    // 处理 offer 事件
    socket.on("offer", async ({ offer, userId, roomId }) => {
      try {
        // 检查是否已存在连接
        let pc = peerConnections.get(userId);
        if (pc) {
          // 如果连接已存在，先关闭旧连接
          pc.close();
        }

        // 创建新连接
        pc = initPeerConnection(userId);
        peerConnections.set(userId, pc);
        setPeerConnections(new Map(peerConnections));

        pc.ontrack = (event) => {
          console.log("收到轨道:", event.track.kind, "来自用户:", userId);
          if (event.streams[0]) {
            const newStreams = new Map(remoteStreams);
            newStreams.set(userId, event.streams[0]);
            setRemoteStreams(newStreams);
          }
        };

        // // 确保连接状态正确
        // if (pc.signalingState !== "stable") {
        //   console.log("重置连接状态");
        //   await Promise.all([
        //     pc.setLocalDescription({ type: "rollback" }),
        //     pc.setRemoteDescription(new RTCSessionDescription(offer)),
        //   ]);
        // } else {
        //   await pc.setRemoteDescription(new RTCSessionDescription(offer));
        // }

        // 先设置远程描述
        await pc.setRemoteDescription(new RTCSessionDescription(offer));

        const answer = await pc.createAnswer();
        await pc.setLocalDescription(answer);

        socket.emit("answer", {
          answer,
          userId: socket.id,
          targetUserId: userId,
          roomId,
        });
      } catch (error) {
        console.error("处理offer失败:", error);
        message.error("建立连接失败");
      }
    });

    // 处理 answer 事件
    socket.on("answer", async ({ answer, userId }) => {
      const pc = peerConnections.get(userId);
      if (pc) {
        try {
          // 检查连接状态并等待稳定
          // if (pc.signalingState !== "stable") {
          //   console.log("等待连接状态稳定...");
          //   await new Promise((resolve) => setTimeout(resolve, 1000));
          // }

          // if (pc.signalingState === "have-local-offer") {
          //   await pc.setRemoteDescription(new RTCSessionDescription(answer));
          // } else {
          //   console.warn("连接状态不正确，当前状态:", pc.signalingState);
          //   // 尝试重新建立连接
          //   if (stream) {
          //     console.log("尝试重新建立连接...");
          //     socket.emit("reconnect-request", {
          //       userId: socket.id,
          //       targetUserId: userId,
          //     });
          //   }
          // }

          await pc.setRemoteDescription(new RTCSessionDescription(answer));
        } catch (error) {
          console.error("处理answer失败:", error);
          message.error("建立连接失败");

          // 如果失败，尝试重新建立连接
          if (stream) {
            console.log("尝试重新建立连接...");
            socket.emit("reconnect-request", {
              userId: socket.id,
              targetUserId: userId,
            });
          }
        }
      }
    });

    // 处理 ICE 候选信息
    socket.on("ice-candidate", async ({ candidate, userId }) => {
      const pc = peerConnections.get(userId);
      if (pc) {
        try {
          // 添加缓冲逻辑，等待远程描述设置完成
          if (pc.remoteDescription && pc.remoteDescription.type) {
            await pc.addIceCandidate(new RTCIceCandidate(candidate));
          } else {
            // 如果远程描述还未设置，等待一段时间后重试
            setTimeout(async () => {
              try {
                if (pc.remoteDescription && pc.remoteDescription.type) {
                  await pc.addIceCandidate(new RTCIceCandidate(candidate));
                }
              } catch (error) {
                console.error("重试添加ICE候选失败:", error);
              }
            }, 1000);
          }
        } catch (error) {
          console.error("添加ICE候选失败:", error);
        }
      }
    });

    // 处理用户离开事件
    socket.on("user-left", (userId) => {
      // 清理指定用户的连接和流
      const pc = peerConnections.get(userId);
      if (pc) {
        pc.close();
        peerConnections.delete(userId);
        setPeerConnections(new Map(peerConnections));
      }

      const stream = remoteStreams.get(userId);
      if (stream) {
        stream.getTracks().forEach((track) => track.stop());
        remoteStreams.delete(userId);
        setRemoteStreams(new Map(remoteStreams));
      }

      message.info(`用户 ${userId} 已离开`);
    });

    // 处理屏幕共享结束事件
    socket.on("share-ended", (userId) => {
      console.log(`用户 ${userId} 结束了共享`);
      message.info("屏幕共享已结束");

      // 清理指定用户的连接和流
      const pc = peerConnections.get(userId);
      if (pc) {
        pc.close();
        peerConnections.delete(userId);
        setPeerConnections(new Map(peerConnections));
      }

      const stream = remoteStreams.get(userId);
      if (stream) {
        stream.getTracks().forEach((track) => track.stop());
        const newStreams = new Map(remoteStreams);
        newStreams.delete(userId);
        setRemoteStreams(newStreams);
      }
    });

    // 处理房主离开
    socket.on("host-left", (roomId) => {
      message.info(`房主已离开${roomId}房间`);
      cleanup();
    });

    // 处理观众离开
    socket.on("viewer-left", (data) => {
      message.info(`用户 ${data.userId} 已离开房间`);
      cleanup();
    });

    // 组件卸载时清理所有事件监听
    return () => {
      cleanupEvents(); // 组件卸载时也清理一次
    };
  }, [
    socket,
    peerConnections,
    initPeerConnection,
    setRemoteStreams,
    remoteStreams,
    setPeerConnections,
    stream,
    roomId,
  ]);

  // 提供一个清理函数供外部使用
  const cleanup = () => {
    remoteStreams.forEach((stream) => {
      stream.getTracks().forEach((track) => track.stop());
    });
    setRemoteStreams(new Map());

    peerConnections.forEach((pc) => {
      pc.close();
    });
    setPeerConnections(new Map());
  };

  return {
    cleanup,
  };
};
